#!/bin/sh
# resner@e.email, resner@notabug.org

downloader="wget"

help="
build/kernel.sh		shell utility for fetching and building the Linux kernel

	[args]

	-h			show help.
*	-k (kernel version)	specify kernel version.
	-j (threads)		specify how many threads to use with make.
	-d			compile with default config.
	-x			only download and extract Linux source tarball.
"

use_defconfig=false
compile=true
make_jobs=8

error() {
	printf "\e[31mError\e[0m: %s\n" "$1"
}

print() {
	printf "%s\n" "$1"
}

while getopts hk:j:dx option; do
	case $option in
	h)
		print "$help"
		exit
		;;
	k) kernel_version="$OPTARG" ;;
	j) make_jobs=$OPTARG ;;
	d) use_defconfig=true ;;
	x) compile=false ;;
	\?)
		error "Unknown flag passed."
		exit 1
		;;
	esac
done

if [ -z "$kernel_version" ]; then
	error "Kernel version not provided."
	exit 1
fi

make_command="make -j$make_jobs"

extract() {
	mkdir $2
	print "Extracting $1 to $2..."
	tar -xvf $1 $2 || exit 1
}

build() {
	if ! $compile; then
		print "Not building."
		return
	fi

	cd "$1" || exit 1

	if $use_defconfig; then
		print "Using default configs."
		$make_command defconfig
	else
		print "Opening menuconfig."
		# run 'make menuconfig' and exit with an error if anything goes wrong.
		$make_command menuconfig || exit 1
	fi

	print "Beginning build..."
	$make_command &&
		print "Finished building."
	exit
}

source_folder="linux-$kernel_version"
source_tarball="linux-$kernel_version.tar.gz"

# build from already extracted source folder if it exists, else extract tarball if it already exists and then build, else download the tarball from kernel.org then extract and build it.
if [ -d "$source_folder" ]; then
	print "Source extraction directory already exists."
	build $source_folder
elif [ -f "$source_tarball" ]; then
	print "Source tarball file already exists."
	extract $source_tarball
	build $source_folder
else
	# parse given kernel version to get the major, minor, and patch versions (ex. 6.0.3 -> [major].[minor].[patch])
	kernel_major=$(echo $kernel_version | awk -F. '{ print $1 }')
	kernel_minor=$(echo $kernel_version | awk -F. '{ print $2 }')
	kernel_patch=$(echo $kernel_version | awk -F. '{ print $3 }')

	print "Fetching kernel $kernel_major.$kernel_minor.$kernel_patch from cdn.kernel.org..."

	base_url="https://cdn.kernel.org"

	# check if the kernel version given is a release candidate, and if it is change the base url that the tarball will be fetched from to git.kernel.org/torvalds/t/, as git snapshots are not available at cdn.kernel.org.
	if echo $kernel_minor | grep -q rc; then
		base_url="https://git.kernel.org"
		server_tarball_parentdir="torvalds/t"
	else
		server_tarball_parentdir="pub/linux/kernel/v$kernel_major.x"
	fi
	$downloader "$base_url/$server_tarball_parentdir/linux-$kernel_version.tar.gz"

	extract $source_tarball
	build $source_folder
fi

print "Finished."
